package com.hinner.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hinner.entity.Chinas;
import com.hinner.entity.dto.RegionDTO;
import com.hinner.exception.CustomException;
import com.hinner.mapper.ChinasMapper;
import com.hinner.service.ChinasService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class ChinasServiceImpl extends ServiceImpl<ChinasMapper, Chinas> implements ChinasService {
    private static final Logger log = LoggerFactory.getLogger(ChinasServiceImpl.class);

    @Autowired
    private ChinasMapper chinasMapper;

    /**                    鼓楼区
     *          南京市 ---  建邺区
     *                     秦淮区
     *                     虎丘区
     * 江苏省--- 苏州市 ---  姑苏区
     *                     工业园区
     *
     *                    如皋市
     *          南通市 --- 海门区
     *                    启东市
     * 省的code是市的pid
     *
     * @return
     */
    @Override
    public List<Chinas> getRegions() {


        //1. 省数据
        LambdaQueryWrapper<Chinas> wrapper = new LambdaQueryWrapper<Chinas>().eq(Chinas::getPid, 0L).eq(Chinas::getLevel, "1");
        List<Chinas> provinces = chinasMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(provinces)){
            throw new CustomException("暂无行政区划数据");
        }
        List<Long> pidList= new ArrayList<>();
        provinces.forEach(province -> pidList.add(province.getCode()));//所有省的code抽出来，作为市的父id


        //2. 市数据：
        wrapper = new LambdaQueryWrapper<Chinas>().eq(Chinas::getLevel, "2").in(Chinas::getPid, pidList);
        List<Chinas> tempCityList = chinasMapper.selectList(wrapper);
        // 根据所有省code分好组后的市数据
        Map<Long, List<Chinas>> map = tempCityList.stream().collect(Collectors.groupingBy(Chinas::getPid));
        // 一个省code取出一份市区数据集合,并添加到省的cityList中
        provinces.stream().forEach(province -> province.setCityList(map.get(province.getCode())));

        // 市的code全部提取出来
        List<Long> cityCodes = new ArrayList<>();
        tempCityList.forEach(item -> cityCodes.add(item.getCode()));


        //3. 县数据
        wrapper = new LambdaQueryWrapper<Chinas>().eq(Chinas::getLevel,"3").in(Chinas::getPid,cityCodes);
        List<Chinas> tempAreaList = chinasMapper.selectList(wrapper);
        Map<Long, List<Chinas>> map2 = tempAreaList.stream().collect(Collectors.groupingBy(Chinas::getPid));
        tempCityList.stream().forEach(chinas -> chinas.setAreaList(map2.get(chinas.getCode())));

        log.info("==========> 省份" + provinces.size());  //34
        log.info("==========> 市份" + tempCityList.size()); // 350
        log.info("==========> 地区" + tempAreaList.size()); // 3059



        return provinces;
    }

    @Override
    public Chinas getRegionByCode(String code) {
        if (StringUtils.isEmpty(code)){
            throw new CustomException("请输入需要查询行政区号");
        }
        LambdaQueryWrapper<Chinas> wrapper;
        Chinas chinas;
        //1. 判断有没有父行政区
        wrapper = new LambdaQueryWrapper<Chinas>().eq(Chinas::getCode, code);
        chinas = this.getOne(wrapper);
        if (ObjectUtil.isEmpty(chinas)) return null;

        //1. 自己是一级行政区
        if ("1".equals(chinas.getLevel())) return chinas; //自己就一级行政区

        //2. 查询父行政区
        //2.1 自己是二级行政区

        if ("2".equals(chinas.getLevel())){
            // 查一级
            wrapper = new LambdaQueryWrapper<Chinas>().eq(Chinas::getCode,chinas.getPid());
            Chinas res = this.getOne(wrapper);
            res.setCityList(Arrays.asList(chinas));
            return res;
        }

        //2.2 自己是三级行政区
        if ("3".equals(chinas.getLevel())){
            //查2级
            wrapper = new LambdaQueryWrapper<Chinas>().eq(Chinas::getCode,chinas.getPid());
            Chinas res = this.getOne(wrapper);
            res.setAreaList(Arrays.asList(chinas));

            //查一级
            wrapper = new LambdaQueryWrapper<Chinas>().eq(Chinas::getCode,res.getPid());
            Chinas tmp = this.getOne(wrapper);
            tmp.setCityList(Arrays.asList(res));
            System.out.println("三级"+tmp);
            return tmp;
        }

        return null;  // 没有找到父行政区
    }

    @Override
    public String getRegionNameByCode(String cityCode) {
        if (StrUtil.isBlank(cityCode)){
            throw new CustomException("城市编码不能为空~");
        }
        LambdaQueryWrapper<Chinas> wrapper = new LambdaQueryWrapper<Chinas>().eq(Chinas::getCode, cityCode);
        Chinas chinas = this.getOne(wrapper);
        return ObjectUtil.isNotEmpty(chinas) ? chinas.getName(): null;
    }

    /**
     * 跟一个城市代码，获取该城市的父级的全称
     * 比如：输入320682代表如皋市
     * 返回：江苏省南通市如皋市
     * @param code
     * @return
     */
    @Override
    public String wholeNameByCode(String code) {
        if (ObjectUtil.isEmpty(code)){
            throw new CustomException("输入的城市编码不合法~");
        }

        Chinas chinas = this.getRegionByCode(code);
        if (ObjectUtil.isEmpty(chinas)) return null;

        String res = chinas.getName();
        if (ObjectUtil.isEmpty(chinas.getCityList())) return res;

        res += chinas.getCityList().get(0).getName();
        List<Chinas> areaList = chinas.getCityList().get(0).getAreaList();
        if (CollectionUtils.isEmpty(areaList)) return res;

        res += areaList.get(0).getName();
        return res;
    }

    @Override
    public List<RegionDTO> regions() {
        List<RegionDTO> list = new ArrayList<>();

        List<Chinas> regions = getRegions();
        for (Chinas region : regions) {
            RegionDTO dto = new RegionDTO();
            dto.setText(region.getName());
            dto.setValue(region.getCode());

            List<Chinas> cityList = region.getCityList();
            List<RegionDTO> secondChildList = new ArrayList<>();
            for (Chinas chinas : cityList) {
                RegionDTO dto2 = new RegionDTO();
                dto2.setText(chinas.getName());
                dto2.setValue(chinas.getCode());

                List<Chinas> areaList = chinas.getAreaList();
                List<RegionDTO> thirdChildList = new ArrayList<>();
                if (CollectionUtils.isEmpty(areaList)) continue;
                for (Chinas area : areaList) {
                    RegionDTO dto3 = new RegionDTO();
                    dto3.setText(area.getName());
                    dto3.setValue(area.getCode());
                    thirdChildList.add(dto3);
                }
                dto2.setChildren(thirdChildList);
                secondChildList.add(dto2);
            }
            dto.setChildren(secondChildList);
            list.add(dto);
        }

        return list;
    }

    @Override
    public List<RegionDTO> getChildRegions(String id) {
        LambdaQueryWrapper<Chinas> wrapper = new LambdaQueryWrapper<Chinas>()
                .eq(StringUtils.isNotEmpty(id), Chinas::getPid, id);
        List<Chinas> list = this.list(wrapper);
        if (CollectionUtils.isEmpty(list)) return null;
        // 如果二级地级市只有一个，那么查三级，例子：直辖市
        if (list.size() == 1){
            Long code = list.get(0).getCode();
            wrapper = new LambdaQueryWrapper<Chinas>()
                    .eq(StringUtils.isNotEmpty(id), Chinas::getPid, code);
            list = this.list(wrapper);
            List<RegionDTO> resList = new ArrayList<>();
            for (Chinas chinas : list) {
                RegionDTO dto = new RegionDTO();
                dto.setValue(chinas.getCode());
                dto.setText(chinas.getName());
                resList.add(dto);
            }
            return resList;
        }
        // 如果二级地级市超过2个，说明不是地级市。
        List<RegionDTO> resList = new ArrayList<>();
        for (Chinas chinas : list) {
            RegionDTO dto = new RegionDTO();
            dto.setValue(chinas.getCode());
            dto.setText(chinas.getName());
            resList.add(dto);
        }
        return resList;
    }
}
